<!DOCTYPE html>
<html lang=en>

<head>
  <meta charset=UTF-8>
  <title>Three.js dancing Tree (for Xmas)</title>
  <meta name=viewport content="width=device-width,initial-scale=1">
  <link rel="shortcut icon" type=image/png href=https://bu.dusays.com/2022/05/17/6283c38e6368f.ico>
  <link rel=stylesheet href=https://use.typekit.net/bji5ovt.css>
  <link rel=stylesheet href=https://npm.elemecdn.com/ethan4116-blog/lib/effect/dancing-tree/style.css>

<body><canvas class=webgl></canvas>
  <h1><small>With</small> Seasonal Wishes <small>from</small> PeHaa</h1><button id=play-music type=button>Play
    music</button>
  <script type=x-shader/x-vertex id=vertexShader>uniform float uTime;
  uniform float uSize;
  attribute float aScale;
  attribute vec3 aColor;
  attribute float phi;
  attribute float random;
  //attribute float random1;
  varying vec2 vUv;
  varying vec3 vColor;
  
  void main() {
    float angle = phi;
    angle += uTime * random;
    angle = mod(angle, 39.3);
    float radius = 0.065 * angle;
    float rand = (random - 0.5) * 0.05 * pow(angle, .75);
    vec3 myOffset =
        vec3(radius * cos(angle) + rand,
             2.9 - 2.7 * radius + rand +
                 0.1 * (random - .5) * pow(angle, .25) * sin(2.0 * uTime),
             radius * sin(angle) + rand);
    vec3 myPosition = myOffset;
    vec4 modelPosition = modelMatrix * vec4(myPosition, 1.0);
  
    vec4 viewPosition = viewMatrix * modelPosition;
    viewPosition.xyz += position * aScale * uSize;
    gl_Position = projectionMatrix * viewPosition;
  
    vColor = aColor;
    vUv = uv;
  }</script>
  <script type=x-shader/x-fragment id=fragmentShader>varying vec3 vColor;
  varying vec2 vUv;
  
  void main() {
    vec2 uv = vUv;
    vec3 color = vColor;
    float strength = distance(uv, vec2(0.5));
    strength *= 2.0;
    strength = 1.0 - strength;
    gl_FragColor = vec4(strength * color, 1.0);
  }</script>
  <script type=x-shader/x-vertex id=vertexShaderExt>#define M_PI 3.1415926535897932384626433832795
  varying float vColorMix;
  varying vec2 vUv;
  uniform float uTime;
  
  vec3 mod289(vec3 x) {
    return x - floor(x * (1.0 / 289.0)) * 289.0;
  }
  
  vec4 mod289(vec4 x) {
    return x - floor(x * (1.0 / 289.0)) * 289.0;
  }
  
  vec4 permute(vec4 x) {
       return mod289(((x*34.0)+1.0)*x);
  }
  
  vec4 taylorInvSqrt(vec4 r)
  {
    return 1.79284291400159 - 0.85373472095314 * r;
  }
  
  float snoise(vec3 v)
    {
    const vec2  C = vec2(1.0/6.0, 1.0/3.0) ;
    const vec4  D = vec4(0.0, 0.5, 1.0, 2.0);
  
  // First corner
    vec3 i  = floor(v + dot(v, C.yyy) );
    vec3 x0 =   v - i + dot(i, C.xxx) ;
  
  // Other corners
    vec3 g = step(x0.yzx, x0.xyz);
    vec3 l = 1.0 - g;
    vec3 i1 = min( g.xyz, l.zxy );
    vec3 i2 = max( g.xyz, l.zxy );
  
    //   x0 = x0 - 0.0 + 0.0 * C.xxx;
    //   x1 = x0 - i1  + 1.0 * C.xxx;
    //   x2 = x0 - i2  + 2.0 * C.xxx;
    //   x3 = x0 - 1.0 + 3.0 * C.xxx;
    vec3 x1 = x0 - i1 + C.xxx;
    vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
    vec3 x3 = x0 - D.yyy;      // -1.0+3.0*C.x = -0.5 = -D.y
  
  // Permutations
    i = mod289(i);
    vec4 p = permute( permute( permute(
               i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
             + i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
             + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
  
  // Gradients: 7x7 points over a square, mapped onto an octahedron.
  // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
    float n_ = 0.142857142857; // 1.0/7.0
    vec3  ns = n_ * D.wyz - D.xzx;
  
    vec4 j = p - 49.0 * floor(p * ns.z * ns.z);  //  mod(p,7*7)
  
    vec4 x_ = floor(j * ns.z);
    vec4 y_ = floor(j - 7.0 * x_ );    // mod(j,N)
  
    vec4 x = x_ *ns.x + ns.yyyy;
    vec4 y = y_ *ns.x + ns.yyyy;
    vec4 h = 1.0 - abs(x) - abs(y);
  
    vec4 b0 = vec4( x.xy, y.xy );
    vec4 b1 = vec4( x.zw, y.zw );
  
    //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
    //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
    vec4 s0 = floor(b0)*2.0 + 1.0;
    vec4 s1 = floor(b1)*2.0 + 1.0;
    vec4 sh = -step(h, vec4(0.0));
  
    vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
    vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
  
    vec3 p0 = vec3(a0.xy,h.x);
    vec3 p1 = vec3(a0.zw,h.y);
    vec3 p2 = vec3(a1.xy,h.z);
    vec3 p3 = vec3(a1.zw,h.w);
  
  //Normalise gradients
    vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
    p0 *= norm.x;
    p1 *= norm.y;
    p2 *= norm.z;
    p3 *= norm.w;
  
  // Mix final noise value
    vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
    m = m * m;
    return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
                                  dot(p2,x2), dot(p3,x3) ) );
    }
  
  
  mat3 rotation3dY(float angle) {
    float s = sin(angle);
    float c = cos(angle);
  
    return mat3(
      c, 0.0, -s,
      0.0, 1.0, 0.0,
      s, 0.0, c
    );
  }
  
  vec3 rotateY(vec3 v, float angle) {
    return rotation3dY(angle) * v;
  }
  
  
  void main() {
    float t = uTime * 0.1;
    float n = snoise(vec3(position.xy, t)*.2 + t);
    vec3 pos = position + n * 0.1;
    pos += 0.1*snoise(pos + t);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
    vUv = uv;
    vColorMix = n;
  }</script>
  <script type=x-shader/x-fragment id=fragmentShaderExt>varying float vColorMix;
  varying vec2 vUv;
  
  void main() {
    float n = vColorMix;
    vec2 uv = vUv;
    gl_FragColor = vec4(mix(vec3(uv, 1.0), vec3(0.0, 1.0, 1.0), 1.0 - n*n) , n * n * n );
  }</script>
  <script type=module src=https://npm.elemecdn.com/ethan4116-blog/lib/effect/dancing-tree/script.js></script>